﻿using System;
using System.Text;
using Maple.Weixin.MP.Entities.JsonResult;
using Maple.Weixin.MP.Exceptions;
using Maple.Weixin.MP.Helpers;
using Newtonsoft.Json;

namespace Maple.Weixin.MP
{
    public abstract class AccessTokenContainerBase : IAccessTokenContainer
    {
        protected readonly string appid;
        protected readonly string appsecret;

        protected AccessTokenContainerBase(string appid, string appsecret) {
            this.appid = appid;
            this.appsecret = appsecret;
        }

        #region Implementation of IAccessTokenContainer

        public abstract string GetAccessToken(bool getNewToken = false);

        #endregion
    }

    public class AccessTokenContainer : AccessTokenContainerBase
    {
        private string accessToken;
        private DateTime expireTime; 

        public AccessTokenContainer(string appid, string appsecret)
            : base(appid, appsecret) {
            this.expireTime = DateTime.MinValue;
        }

        #region Implementation of IAccessTokenContainer

        public override string GetAccessToken(bool getNewToken = false) {
            if (expireTime >= DateTime.Now && !getNewToken)
                return accessToken;

            var url = WeixinHelper.GetAccessUrl(appid, appsecret);
            var returnText = HttpHelper.Get(url, Encoding.UTF8);
            if (returnText.Contains("errorcode"))
            {
                var errorResult = JsonConvert.DeserializeObject<WeixinServiceResult>(returnText);
                if ((int)errorResult.errcode != 0)
                    throw new WeixinRequestException(
                        string.Format("获取access_token发生异常！错误代码：{0}，说明：{1}", errorResult.errcode, errorResult.errmsg), null,
                        errorResult);
            }

            var result = JsonConvert.DeserializeObject<AccessTokenResult>(returnText);
            accessToken = result.access_token;
            int seconds = result.expires_in / 2;  // 设置一半时间过期
            expireTime = DateTime.Now.AddSeconds(seconds);
            return accessToken;
        }

        #endregion
    }
}
